// code 4: static/global mutex_lock, 将数据封装成对象传入线程
#include <unistd.h>
#include <pthread.h>
#include <iostream>
#include <string>
using namespace std;
// critical resource
int tickets = 10000;
struct thread_acgcs
{
    thread_acgcs(string &name, pthread_mutex_t *pmutex)
        : _name(name), _pmutex(pmutex)
    {
        ;
    }

    thread_acgcs(string &&name, pthread_mutex_t *pmutex)
        : _pmutex(pmutex)
    {
        _name.swap(name);
    }

    string _name;
    pthread_mutex_t *_pmutex;
};
void *thread_todo_func(void *argcs)
{
    thread_acgcs *argcs_obj = reinterpret_cast<thread_acgcs *>(argcs);
    while (true)
    {
        pthread_mutex_lock(argcs_obj->_pmutex);
        //Critical Section
        if (tickets)
        {
            cout << argcs_obj->_name << " get ticket: " << tickets-- << endl;
            pthread_mutex_unlock(argcs_obj->_pmutex);
            // other codes
            usleep(999);
        }
        else
        {
            pthread_mutex_unlock(argcs_obj->_pmutex);
            cout << argcs_obj->_name << ":: no ticket left" << endl;
            // other codes
            usleep(123);
            break;
        }
    }
    return nullptr;
}
int main()
{
    //全局和静态的互斥锁,可以选择直接使用宏初始化,若如此做,不用调mutex_destroy.
    static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
    pthread_t tid_1;
    pthread_t tid_2;
    pthread_t tid_3;
    pthread_t tid_4;
    thread_acgcs *thread_acgcs_1 = new thread_acgcs(string("thread_1"), &s_mutex);
    thread_acgcs *thread_acgcs_2 = new thread_acgcs(string("thread_2"), &s_mutex);
    thread_acgcs *thread_acgcs_3 = new thread_acgcs(string("thread_3"), &s_mutex);
    thread_acgcs *thread_acgcs_4 = new thread_acgcs(string("thread_4"), &s_mutex);

    pthread_create(&tid_1, nullptr, thread_todo_func, reinterpret_cast<void *>(thread_acgcs_1));
    pthread_create(&tid_2, nullptr, thread_todo_func, reinterpret_cast<void *>(thread_acgcs_2));
    pthread_create(&tid_3, nullptr, thread_todo_func, reinterpret_cast<void *>(thread_acgcs_3));
    pthread_create(&tid_4, nullptr, thread_todo_func, reinterpret_cast<void *>(thread_acgcs_4));

    pthread_join(tid_1, nullptr);
    pthread_join(tid_2, nullptr);
    pthread_join(tid_3, nullptr);
    pthread_join(tid_4, nullptr);

    delete thread_acgcs_1;
    delete thread_acgcs_2;
    delete thread_acgcs_3;
    delete thread_acgcs_4;

    return 0;
}